package com.coupon.filters;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 自定义GlobalFilter，当请求进入时记录开始时间，当请求结束时，减去开始时间即为具体的执行时长
 * @author mo_chou_555
 * */
@Slf4j
@Component
public class LogFilter implements GlobalFilter, Ordered {
    private static final String START_TIME = "startTime";

    /**类似doFilter
     * webFlux中没有servletReq和servletResp对象
     * 类似使用的是exchange对象，exchange代表交换，req和resp的功能都被封装在了exchange中
     * webFlux中的req和resp是server模型，而非servlet模型
     * */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取req和resp
        final ServerHttpRequest request = exchange.getRequest();

        //填充当前时间戳为起始时间
        exchange.getAttributes().put(START_TIME, System.currentTimeMillis());
        //放行
        return chain.filter(exchange)
                //响应回来再处理
                .then( Mono.fromRunnable(() -> {
            //获取起始时间
            Long startTime = exchange.getAttribute(START_TIME);
            if (startTime != null) {
                //当前时间-起始时间为执行时间
                long executeTime = (System.currentTimeMillis() - startTime);
                //打印执行时间
                log.info(request.getURI().getRawPath() + " : " + executeTime + "ms");
            }
        }));
    }

    /**int数字，指定filter执行顺序，默认按照自然数字进行排序
     * 最小可为-1，在所有执行之前执行。
     * 最大为LOWEST_PRECEDENCE，integer的最大值，在所有执行之后执行
     * 默认值0，一般为最先执行（-1除外）
     * */
    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
}
